/*
 * table_FileIndex.c
 *
 *  Created on: 2012/03/26
 *      Author: guanxiaoying
 */
#include "../../parser/coredef.h"

/* KIND_FILEINDEX	 */
typedef struct _FILEINDEX
{
	AST         astName;
	U4          ulSize;
	S4          modifyTime;
	AST         astParent;
	AST         astEntry;
	RBTREE   	rbtree;
	UCHAR       bFolder;
	UCHAR       bExist;
	AST			transUnit;
} FILEINDEX, *PFILEINDEX;


static AST              topRoot = 0;
static CHAR  staticbuffer [OS_FULLPATH + 2] = "";
#define TableSize  (sizeof(FILEINDEX))
#define TableType  PFILEINDEX
#define stTable stFileManager.memoryBlocks
#define maxTable stFileManager.maxRecordNum
#define  maxNumPerBlk  (stFileManager.astMaxNum_Block)

/* private field */


static TABLEMANAGER stFileManager = {
//		U4                  usIdx;
		0,
//		PSZ				    con_pszName;    constant
		__FILE__,
//		U2					con_usSize;		constant
		TableSize,
//		U2					block_num;	　　　　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_Block;     １回設定のみ
		0,
//		S4					astTabNum_LastPage; 　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_LastPage;     Reset clear  際　要
		0,
//		U4					ulMaxByte;	　　　　　　　　　　クリアしない
		0,
//		U4					con_minPageSize;　　　　　　　　　　constant
		0
};
static VOID resetListener( U4  procid, U2 index )
{
	if( procid == stFileManager.u4Idx )
	{
		if( index > 0 && index < MAX_VOLUMN_OF_TABLE )
		{
			stTable[ index-1] = NULL;
		}
	}
}
static TableType core_getTable( AST index )
{
	TableType temp = (TableType)Check_Com( &stFileManager, resetListener,  index );
	if( temp != NULL ){ return &temp[index%maxNumPerBlk]; } return NULL;
}
static BOOL ClearTable( VOID )
{
	topRoot = 0;
	return Clear_Com( &stFileManager );
}
static BOOL ResetTable( VOID )
{
	topRoot = 0;
	return Reset_Com( &stFileManager );
}
static BOOL AllocTable( AST astReqArg )
{
	return AllocTable_Com( &stFileManager, astReqArg, resetListener );
}
/*D*/
/**************************************************************************
* 関 数 名 : copyTable
* 機    能 : 同じテーブルの行のブロックを移動する
* 引 き 数 ：
* 　　　　　　　astOrg :コピー元の開始行の連番
* 		　astDst：　コピー先の開始行の連番
*         astlenth: ブロック中の行の数
* 戻 り 値 : 成功する場合、1。失敗する場合、0
* 詳細内容 :  メモリ移動
************************************************************************/
static BOOL copyTable( AST  astOrg,  AST  astDst,  AST astLenth )
{
	return Copy_Com( &stFileManager, resetListener, astOrg, astDst, astLenth );
}

static AST  getMaxLines( VOID )
{
	return maxTable;
}
/* give up the way that defining get/set function pointer in the struct,
 * because of memory volume.
 */

/* new   get method */
static U4   Get_FileSize( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->ulSize;
}

/* new   get method */
static S4   Get_ModifyTime( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->modifyTime;
}

/* STR_FILENAME   set method */
static AST   Set_Path( AST index, CHAR * pszStr  )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		assert_index( maxFileIndex, index, (S4)pszStr );
		return 0;
	}
	return pTbl->astName = stCoreLabelStrAccess.addStr( pszStr );
}
//ACCESS_IDX_FIELD entry;
static AST   getEntry( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( !pTbl->bFolder )
	{
		return 0;
	}
	return pTbl->astEntry;
}
/* IDX_SOURCE   set method */
static AST   setEntry( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		assert_index( maxFileIndex, index, astTu );
		return 0;
	}
	return pTbl->astEntry = value;
}
//ACCESS_BOOL_FIELD bFolder;
static BOOL   isFolder( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->bFolder;
}

static BOOL   isExisted( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->bExist;
}
static S4	cmp_path_str ( AST	astpath, void* pszStr )
{
	PSZ		pszname;
	PSZ		psznameintree;
	S4 ret;

	if( astpath == 0 )
	{
		return RBT_LESS;
	}
	pszname = (PSZ)pszStr;
	if( pszname == 0 || *pszname == '\0' )
	{
		return RBT_FOUND;
	}
	psznameintree = stCoreLabelStrAccess.getStr(astpath);
	if( psznameintree == NULL || *psznameintree == '\0' )
	{
		return RBT_LARGER;
	}
	ret = cmpPath( pszname, psznameintree );
	if( ret < 0 )
	{
		return RBT_LESS;
	}else if( ret > 0 )
	{
		return RBT_LARGER;
	}
	return RBT_FOUND;
}
static AST getLeft( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astLeftChild;
}
static AST setLeft( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astLeftChild = value;
}
static AST getRight( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astRightChild;
}
static AST setRight( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astRightChild = value;
}
static AST getParent( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astParent;
}
static AST setParent( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astParent = value;
}
static AST getIndex( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astName;
}
static U2 getColor( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.lColor;
}
static U2 setColor( AST index, U2 value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.lColor = value;
}

static ACCESS_RBTREE stAccessRbtree =
{
		AllocTable,
		getMaxLines,
		getIndex,
		{
				getLeft,
				setLeft
		},
		{
				getRight,
				setRight
		},
		{
				getParent,
				setParent
		},
		{
				getColor,
				setColor
		}
};
static PSZ getLastSegmentName( AST astIndex, U4 index ){
	TableType pTbl = core_getTable( index );
	while( index > 1 && pTbl != NULL ){
		pTbl = core_getTable( pTbl->astParent );
		index--;
	}
	if( pTbl != NULL ){
		return stCoreLabelStrAccess.getStr(pTbl->astName);
	}
	return "(null)";
}
static U4  getFilePath( AST index, PSZ buffer, U4 buflen )
{
	U4 size = 0;
	U4 byte = 0;
//	AST cnt = index;
	TableType pTbl = core_getTable( index );
	register PSZ p,p1;
	if( pTbl == NULL )
	{
		return 0;
	}
	while( pTbl->astParent )
	{
		size += str_length(stCoreLabelStrAccess.getStr(pTbl->astName));
		size++;
//		cnt = pTbl->astParent;
		pTbl = core_getTable( pTbl->astParent );
		if( pTbl == NULL )
		{
			return 0;
		}
	}
	
	if( size <= 1 || size > buflen )
	{
		*buffer = '\0';
		return 0;
	}
	size--;
	byte = size;
//	cnt = index;
	pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	buffer[size] = '\0';
	while( pTbl->astParent )
	{
		p = stCoreLabelStrAccess.getStr(pTbl->astName);
		size -= str_length(stCoreLabelStrAccess.getStr(pTbl->astName)) + 1;
		p1 = buffer + size ;
		*p1 = PATH_DELIMITER;
		p1++;
		while(*p != '\0')
		{
			*p1 = *p;
			p++;
			p1++;
		}
//		cnt = pTbl->astParent;
		pTbl = core_getTable( pTbl->astParent );
		if( pTbl == NULL )
		{
			return 0;
		}
	}
	return byte;
}
static AST  addFilePath( PSZ path )
{
	PSZ p;
	BOOL bRet ;
	S4 nRet;
	PATH_PIECES * header;
	AST astRet = 0;
	AST astNew = 0;
	AST astRoot = 0;
	AST astParent = 0;
	TableType pTbl;
	BOOL bExist = FALSE, bFolder = FALSE;
    if( str_length( path ) == 0 )
    {
    	return 0;
    }
	if( !IsFullPath(path) ){
	    bRet = GetFullPath( path, staticbuffer, OS_FULLPATH );
	    if( bRet == FALSE )
	    {
	    	return 0;
	    }
	    path = staticbuffer;
	}
	if( topRoot == 0 )
	{
		bRet = AllocTable( 1 );
		if( bRet == FALSE )
		{
			return 0;
		}
		topRoot = maxTable;
		pTbl = core_getTable( maxTable );
		if( pTbl == NULL )
		{
			return 0;
		}
		pTbl->bExist = FALSE;
		pTbl->bFolder = TRUE;
	}
	BREAK_PATH1(path,header);
	astParent = topRoot;
	if( COEXIT_FOUND ==  FileCheckExists(path) )
	{
		bExist = TRUE;
	}
	if( COEXIT_FOUND ==  FileCheckDir( path ) )
	{
		bFolder = TRUE;
	}
	while( header != NULL )
	{
		p = header->buffer;
		astRoot = getEntry(astParent);
		nRet = FindData( &stAccessRbtree, astRoot, p, &astRet, cmp_path_str );
		if( nRet != 0 )
		{
			astNew = 0;
			bRet = InsertData( &stAccessRbtree, nRet, astRet, &astRoot, &astNew );
			if( bRet == FALSE )
			{
				return 0;
			}
			setEntry(astParent,astRoot);
			pTbl = core_getTable( astNew );
			if( pTbl == NULL )
			{
				return 0;
			}
			Set_Path( astNew, p );
			pTbl->astParent = astParent;
			if( !pTbl->bExist )
			{
				pTbl->bExist = bExist;
			}
			if( bExist && ( bFolder || header->next != NULL ) )
			{
				pTbl->bFolder = TRUE;
			}
			if( pTbl->bExist && !pTbl->bFolder )
			{
				pTbl->modifyTime = FileGetModifyTime( path );
				pTbl->ulSize = FileGetSize( path );
			}

			/*debug,12/10/02,S*/
			astParent = astNew;
			header = header->next;
		}else{
			astParent = astRet;
			header = header->next;
		}
	}
	return astParent;
	/*debug,12/10/02,E*/
}
/*debug,12/10/16,S*/
static AST  addFilePath_load( PSZ path,S4 time,U4 size,BOOL bFolder,BOOL bExist,AST tu)
{
	PSZ p;
	BOOL bRet ;
	S4 nRet;
	PATH_PIECES * header;
	AST astRet = 0;
	AST astNew = 0;
	AST astRoot = 0;
	AST astParent = 0;
	TableType pTbl;
    if( str_length( path ) == 0 )
    {
    	return 0;
    }
	if( !IsFullPath(path) ){
	    bRet = GetFullPath( path, staticbuffer, OS_FULLPATH );
	    if( bRet == FALSE )
	    {
	    	return 0;
	    }
	    path = staticbuffer;
	}
	if( topRoot == 0 )
	{
		bRet = AllocTable( 1 );
		if( bRet == FALSE )
		{
			return 0;
		}
		topRoot = maxTable;
		pTbl = core_getTable( maxTable );
		if( pTbl == NULL )
		{
			return 0;
		}
		pTbl->bExist = FALSE;
		pTbl->bFolder = TRUE;
	}
	BREAK_PATH1(path,header);
	astParent = topRoot;

	while( header != NULL )
	{
		p = header->buffer;
		astRoot = getEntry(astParent);
		nRet = FindData( &stAccessRbtree, astRoot, p, &astRet, cmp_path_str );
		if( nRet != 0 )
		{
			astNew = 0;
			bRet = InsertData( &stAccessRbtree, nRet, astRet, &astRoot, &astNew );
			if( bRet == FALSE )
			{
				return 0;
			}
			setEntry(astParent,astRoot);
			pTbl = core_getTable( astNew );
			if( pTbl == NULL )
			{
				return 0;
			}
			Set_Path( astNew, p );
			pTbl->astParent = astParent;

			pTbl->bExist = bExist;
			pTbl->bFolder = bFolder;
			pTbl->modifyTime = time;
			pTbl->ulSize = size;
			pTbl->transUnit = tu;

			astParent = astNew;
			header = header->next;
		}else{
			astParent = astRet;
			header = header->next;
		}
	}
	return astParent;
}
/*debug,12/10/16,E*/
static AST getTransUnit( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->transUnit;
}
static AST setTransUnit( AST index, AST idx )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		assert_index( maxTable, index, idx );
		return 0;
	}
	return pTbl->transUnit = idx;
}

const FILEINDEXACCESS stCoreFileIndexAccess = {
//		BOOL (*clear)( VOID );
		ClearTable,
//		BOOL (*reset)( VOID );
		ResetTable,
//		BOOL (*copy)( AST, AST, AST );
		copyTable,
//		AST  (*getMax)( VOID );
		getMaxLines,
//		AST (*addFile)( PSZ );
		addFilePath,
		/*debug,12/10/16,S*/
		addFilePath_load,
		/*debug,12/10/16,E*/
//		U4  (*getFile)( AST index, PSZ buffer, U4 buflen );
		getFilePath,

//		S4  (*getModifyTime)( AST );
		Get_ModifyTime,
//		U4  (*getSize)( AST );
		Get_FileSize,
//		BOOL  (*isFolder)( AST );
		isFolder,
//		BOOL  (*isExisted)( AST );
		isExisted,
		getLastSegmentName,
		{
				getTransUnit,
				setTransUnit
		}
};
/* end of file */

